﻿using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

namespace System;

public static class EnumExtensions
{
    public static TAttribute GetAttribute<TAttribute>(this Enum @enum)
        where TAttribute : Attribute
    {
        try
        {
            return @enum.GetType().GetField(@enum.ToString()).GetCustomAttribute<TAttribute>();
        }
        catch
        {
            return null;
        }
    }

    public static string GetDisplayName(this Enum @enum)
    {
        return GetAttribute<DisplayNameAttribute>(@enum)?.DisplayName ?? GetAttribute<DisplayAttribute>(@enum)?.Name;
    }

    public static string GetDescription(this Enum @enum)
    {
        return GetAttribute<DescriptionAttribute>(@enum)?.Description;
    }

    public static Dictionary<TEnum, string> GetFieldsDictionary<TEnum>()
        where TEnum : Enum
    {
        var values = Enum.GetValues(typeof(TEnum)).OfType<TEnum>();
        return values.ToDictionary(r => r, r => r.ToString());
    }

    public static Dictionary<Enum, string> GetFieldsDictionary(Type type)
    {
        var values = Enum.GetValues(type).OfType<Enum>();
        return values.ToDictionary(r => r, r => r.ToString());
    }

    public static Dictionary<TEnum, string> GetDescriptionsDictionary<TEnum>()
        where TEnum : Enum
    {
        var values = Enum.GetValues(typeof(TEnum)).OfType<TEnum>();
        return values.ToDictionary(r => r, r => r.GetDescription());
    }

    public static Dictionary<Enum, string> GetDescriptionsDictionary(Type type)
    {
        var values = Enum.GetValues(type).OfType<Enum>();
        return values.ToDictionary(r => r, r => r.GetDescription());
    }

    public static Dictionary<TEnum, string> GetDisplayNamesDictionary<TEnum>()
        where TEnum : Enum
    {
        var values = Enum.GetValues(typeof(TEnum)).OfType<TEnum>();
        return values.ToDictionary(r => r, r => r.GetDisplayName());
    }

    public static Dictionary<Enum, string> GetDisplayNamesDictionary(Type type)
    {
        var values = Enum.GetValues(type).OfType<Enum>();
        return values.ToDictionary(r => r, r => r.GetDisplayName());
    }
}

